
using System;
using System.Collections.Generic;
using Xunit.Extensions;


namespace Boilen.Primitives.Members {

    public class TestAccessorMember {

        [Theory]
        [InlineData( "modifiers", "type", "name" )]
        [InlineData( "private", "int", "Count" )]
        public void Write_succeeds_for_valid_arguments( string modifiers, string type, string name ) {
            string[] expectedLines = new[] {
                modifiers + " " + type + " " + name,
                "{",
                "}",
                ""
            };
            var writer = new StringBuilderCodeWriter( );
            var bm = new AccessorMember( name, type ) { Modifiers = modifiers };

            bm.Write( writer );

            var lines = writer.GetLines( );
            AssertExtensions.EqualCollection( lines, expectedLines );
        }

        [Theory]
        [InlineData( null, null )]
        [InlineData( "return x;", null )]
        [InlineData( null, "x = value;" )]
        [InlineData( "return x;", "x = value;" )]
        public void Write_outputs_expected_blocks( string retrieveValue, string assignValue ) {
            string accessorType = "type";
            string accessorName = "accessor";
            var expectedLines = new List<string>( );
            var am = new AccessorMember( accessorName, accessorType );
            expectedLines.Add( am.Modifiers + " " + accessorType + " " + accessorName );
            expectedLines.Add( "{" );
            AddBlock( b => am.ObserveMember = b, expectedLines, "retrieve", retrieveValue );
            AddBlock( b => am.UpdateMember = b, expectedLines, "assign", assignValue );
            expectedLines.Add( "}" );
            expectedLines.Add( "" );
            var writer = new StringBuilderCodeWriter( );

            am.Write( writer );

            string[] lines = writer.GetLines( );
            AssertExtensions.EqualCollection( lines, expectedLines );
        }


        #region Utility

        private static void AddBlock( Action<BlockMember> setBlock, List<string> expectedLines, string name, string value ) {
            const string indent = "    ";
            if( value == null )
                return;

            setBlock( new BlockMember( name, w => w.WriteLine( value ) ) { WriteName = true } );

            expectedLines.Add( indent + name );
            expectedLines.Add( indent + "{" );
            expectedLines.Add( indent + indent + value );
            expectedLines.Add( indent + "}" );
        }

        #endregion

    }

}
